package online

import (
	"fmt"
	"server/common"

	"github.com/mitchellh/mapstructure"
	"github.com/sirupsen/logrus"
)

// -------------------------------------------------------------------------------------------------
//
// -------------------------------------------------------------------------------------------------
func (s *OnlineService) checkCandidateNotifyData(data common.P2PCandidateNotifyData) error {
	// 检查 CallId 是否提供
	if data.CallId == "" {
		return fmt.Errorf("callId is required in candidate notify")
	}

	// 检查 UserId 是否提供
	if data.UserId == "" {
		return fmt.Errorf("userId is required in candidate notify")
	}

	// 检查 Candidate 是否提供
	if data.Candidate == "" {
		return fmt.Errorf("candidate is required in candidate notify")
	}

	// 检查 CallId 是否存在
	if !s.callMgr.CallExists(data.CallId) {
		return fmt.Errorf("callId does not exist: %s", data.CallId)
	}

	// 检查 UserId 是否是 Call 的参与者之一
	if !s.callMgr.UserInCall(data.CallId, data.UserId) {
		return fmt.Errorf("userId is not a participant in the call: %s", data.UserId)
	}

	return nil
}

// -------------------------------------------------------------------------------------------------
//
// -------------------------------------------------------------------------------------------------
func (s *OnlineService) handleCandidateNotify(msg common.Message, from common.ServiceInfo,
	connId string) error {
	common.Logger(common.SERVICE_TYPE_ONLINE, msg.Rid).WithFields(logrus.Fields{
		"msg":    common.ToJson(msg),
		"from":   from,
		"connId": connId,
	}).Info("call handleCandidateNotify")

	// 解析消息数据
	var notifyData common.P2PCandidateNotifyData
	if err := mapstructure.Decode(msg.Data, &notifyData); err != nil {
		common.Logger(common.SERVICE_TYPE_ONLINE, msg.Rid).WithError(err).
			Error("failed to decode candidate notify data")
		return err
	}

	if err := s.checkCandidateNotifyData(notifyData); err != nil {
		common.Logger(common.SERVICE_TYPE_ONLINE, msg.Rid).WithError(err).
			Error("failed to validate candidate notify data")
		return err
	}

	peerUserId, err := s.callMgr.GetPeerUserId(notifyData.CallId, notifyData.UserId)
	if err != nil {
		common.Logger(common.SERVICE_TYPE_ONLINE, msg.Rid).WithError(err).
			Error("failed to get peer user ID")
		return err
	}

	// 获取对端客户端信息
	peerUser := s.userMgr.GetUserByUserId(peerUserId)
	if peerUser == nil {
		err := fmt.Errorf("client does not exist for user ID: %s", peerUserId)
		common.Logger(common.SERVICE_TYPE_ONLINE, msg.Rid).Error(err)
		return err
	}

	// 直接转发 Candidate notify 消息到对端
	if err := s.dispatcher.Dispatch(msg, s.serviceInfo, peerUser.ServiceInfo, peerUser.ConnId); err != nil {
		common.Logger(common.SERVICE_TYPE_ONLINE, msg.Rid).WithError(err).
			Error("failed to forward candidate notify")
		return err
	}

	return nil
}
